package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.exception.CustomException;
import com.heima.feign.article.IArticleClient;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.*;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.*;
import com.heima.wemedia.service.GreenScanService;
import com.heima.wemedia.service.WmNewsAutoScanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 陈辉
 * @data 2023 14:18
 */

@Service
@Slf4j
@Transactional
@SuppressWarnings("all")
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private GreenScanService greenScanService;
    @Autowired
    private IArticleClient articleClient;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private WmChannelMapper wmChannelMapper;
    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 自媒体文章审核
     *
     * @param id 自媒体文章id
     */
    @Override
//    @Async              //  线程池在项目中应用场景  -- 业务的异步调用
    public void autoScanWmNews(Integer id) {
        //1. 根据文章id查询数据库文章信息
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews == null || StringUtils.isBlank(wmNews.getContent())) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //2. 提取文章中的文字和图片  -- 奥利给
        Map<String, Object> map = handleTextAndImage(wmNews);

        //3. 审核文字
        //3.1 先进行自管理敏感词审核逻辑
        boolean isSensitive = handleSensitiveScan((String) map.get("text"), wmNews);
        if(!isSensitive) return;

        //3.2 自管理敏感词审核通过，再调用百度云审核
        //boolean isTextScan = scanText(map.get("text").toString(), wmNews);
        boolean isTextScan = true;
        if (!isTextScan) return;

        //4. 审核图片
        //boolean isImageScan = scanImage((List<String>) map.get("image"), wmNews);
        boolean isImageScan = true;
        if (!isImageScan) return;

        try {
            //5. 远程调用article微服务，进行app文章保存
            ResponseResult result = saveArticle(wmNews);
            //if (result.getCode().equals(200)) {
            if (result.getCode() == 200 ) {
                //调用远程article成功后，需要回填wm_news表中的article_id字段
                wmNews.setArticleId((Long) result.getData());
                wmNews.setReason("审核成功");
                wmNews.setStatus(WmNews.Status.PUBLISHED.getCode());
                wmNewsMapper.updateById(wmNews);
            } else {
                throw new RuntimeException("WmNewsAutoScanServiceImpl --- 同步app文章失败!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("WmNewsAutoScanServiceImpl --- 同步app文章失败!");
        }

    }


    /**
     * 自管理的敏感词审核
     * @param content
     * @param wmNews
     * @return
     */
    public boolean handleSensitiveScan(String content, WmNews wmNews) {

        boolean flag = true;

        //获取所有的敏感词  -- 先从redis中获取
        List<String> sensitiveList = (List<String>) redisTemplate.opsForValue().get("Sensitive");
        if (sensitiveList == null) {
            List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(Wrappers.<WmSensitive>lambdaQuery().select(WmSensitive::getSensitives));
            sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
            //存入redis中
            redisTemplate.opsForValue().set("Sensitive",sensitiveList);
        }

        //初始化敏感词库
        SensitiveWordUtil.initMap(sensitiveList);

        //查看文章中是否包含敏感词
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if(map.size() >0 && wmNews != null){
            wmNews.setStatus(WmNews.Status.FAIL.getCode());
            wmNews.setReason("审核失败：文章存在违规信息:"+map);
            wmNewsMapper.updateById(wmNews);
            flag = false;
        }else if (map.size() >0 && wmNews == null){
            flag = false;
        }

        return flag;
    }

    /**
     * 远程调用article微服务，实现wm_news到ap_article的数据同步
     *
     * @param wmNews
     */
    private ResponseResult saveArticle(WmNews wmNews) {
        //准备一个articleDto
        ArticleDto articleDto = new ArticleDto();
        //从wmNews中将大部分属性拷贝到dto
        BeanUtils.copyProperties(wmNews, articleDto);
        //部分属性需要单独处理
        //1. 作者id
        articleDto.setAuthorId(wmNews.getUserId().longValue());
        //2. 作者名称
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if (wmUser != null) {
            articleDto.setAuthorName(wmUser.getName());
        }
        //3. 文章布局
        articleDto.setLayout(wmNews.getType());
        //4. 频道名称
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if (wmChannel != null) {
            articleDto.setChannelName(wmChannel.getName());
        }
        //5. 文章id
        if (wmNews.getArticleId() != null) {
            //说明是对之前发布过的文章进行修改，这时候需要给app端携带article_id
            articleDto.setId(wmNews.getArticleId());
        }

        ResponseResult result = articleClient.saveOrUpdate(articleDto);
        return result;

    }

    /**
     * 审核图片
     *
     * @param image
     * @param wmNews
     * @return
     */
    private boolean scanImage(List<String> image, WmNews wmNews) {
        //假设文章能审核通过
        boolean flag = true;

        try {
            for (String url : image) {
                //调用百度云API进行内容审核
                Map map = greenScanService.scanImage(url);
                //不通过：修改文章状态
                if ((int) map.get("conclusionType") == WemediaConstants.BAIDU_SCAN_NO_PASS) {
                    flag = false;
                    wmNews.setStatus(WmNews.Status.FAIL.getCode());
                    wmNews.setReason("审核失败：文章图片存在违规");
                    wmNewsMapper.updateById(wmNews);
                    break;
                }
                //疑似：修改文章状态
                if ((int) map.get("conclusionType") == WemediaConstants.BAIDU_SCAN_YS) {
                    flag = false;
                    wmNews.setStatus(WmNews.Status.ADMIN_AUTH.getCode());
                    wmNews.setReason("待人工审核：文章图片疑似存在违规");
                    wmNewsMapper.updateById(wmNews);
                    break;
                }
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

        return flag;
    }

    /**
     * 审核文章中的纯文本内容
     *
     * @param text
     * @param wmNews
     */
    private boolean scanText(String text, WmNews wmNews) {

        //假设文章能审核通过
        boolean flag = true;

        try {
            //调用百度云API进行内容审核
            Map map = greenScanService.scanText(text);
            //不通过：修改文章状态
            if ((int) map.get("conclusionType") == WemediaConstants.BAIDU_SCAN_NO_PASS) {
                flag = false;
                wmNews.setStatus(WmNews.Status.FAIL.getCode());
                wmNews.setReason("审核失败：文章存在违规信息");
                wmNewsMapper.updateById(wmNews);
            }
            //疑似：修改文章状态
            if ((int) map.get("conclusionType") == WemediaConstants.BAIDU_SCAN_YS) {
                flag = false;
                wmNews.setStatus(WmNews.Status.ADMIN_AUTH.getCode());
                wmNews.setReason("待人工审核：文章疑似存在违规信息");
                wmNewsMapper.updateById(wmNews);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return flag;
    }

    /**
     * 提取文章中的文字和图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> handleTextAndImage(WmNews wmNews) {
        if (wmNews != null && StringUtils.isNotEmpty(wmNews.getContent())) {
            String content = wmNews.getContent();
            JSONArray jsonArray = JSON.parseArray(content);

            //定义一个StringBuilder容器用来存放所有的文字
            StringBuilder builder = new StringBuilder(wmNews.getTitle());
            builder.append(wmNews.getLabels());

            //定义一个ArrayList容器用来存放所有的图片
            ArrayList list = new ArrayList();

            //1. 提取文章内容中的所有文字和图片
            for (Object json : jsonArray) {
                JSONObject jsonObject = JSON.parseObject(json.toString());
                if (jsonObject.get("type").equals("text")) {
                    //提取文字
                    builder.append(jsonObject.get("value").toString());
                }
                if (jsonObject.get("type").equals("image")) {
                    //提取图片
                    list.add(jsonObject.get("value").toString());
                }
            }

            //2. 提取封面图片
            String images = wmNews.getImages();
            if (StringUtils.isNotEmpty(images)) {
                String[] split = images.split(",");
                list.addAll(Arrays.asList(split));
            }

            //3. 封装结果map返回
            Map<String, Object> map = new HashMap<>();
            map.put("text", builder.toString());
            map.put("image", list);
            return map;
        }

        return null;
    }
}
